use std::{
    collections::{HashSet, VecDeque},
    time::Instant,
};

use tvk_base::{geometry::mesh::MeshData, math::glam::Mat4, types::handles::MeshHandle};

use crate::{Scene, Segment, SegmentId, command::RenderCommand, geometry::GeometryInstanceSegment};

pub struct RenderBatch {
    commands: VecDeque<RenderCommand>,
    dirty_segments: HashSet<SegmentId>,
    last_flush_time: Instant,
    min_flush_interval_ms: u64,
}

impl RenderBatch {
    /// 创建新的渲染批处理器
    pub fn new(min_flush_interval_ms: u64) -> Self {
        Self {
            commands: VecDeque::new(),
            dirty_segments: HashSet::new(),
            last_flush_time: Instant::now(),
            min_flush_interval_ms,
        }
    }

    pub(crate) fn push_command(&mut self, command: RenderCommand) {
        self.commands.push_back(command);

        // 处理特殊命令，优化脏段标记
        match &self.commands.back().unwrap() {
            RenderCommand::AddGeometry {
                mesh_handle,
                transform: _,
                parent_id: _,
            } => {
                log::debug!("收到了 RenderCommand::AddGeometry 命令 MeshHandle: {:#?}", mesh_handle)
            }
            RenderCommand::UpdateGeometryTransform {
                segment_id,
                transform: _,
            } => {
                // 如果段在脏段集合中，移除它
                self.dirty_segments.insert(*segment_id);
            }
            RenderCommand::RemoveSegment(nice_id) => {
                self.dirty_segments.remove(nice_id);
            }
            _ => (),
        }
    }

    pub(crate) fn process_commands(&mut self, scene: &mut Scene) {
        if self.commands.is_empty() {
            return;
        }

        // 先处理所有RegisterMesh命令，确保网格数据先注册
        let mut register_commands = Vec::new();
        let mut other_commands = Vec::new();

        // 分离命令类型
        while let Some(cmd) = self.commands.pop_front() {
            match &cmd {
                RenderCommand::RegisterMesh { .. } => register_commands.push(cmd),
                _ => other_commands.push(cmd),
            }
        }

        // 处理所有网格注册命令
        for cmd in register_commands {
            if let RenderCommand::RegisterMesh { handle, mesh_data } = cmd {
                scene.mesh_manager_mut().register(handle, mesh_data);
            }
        }

        // 处理其他命令
        for cmd in other_commands {
            match cmd {
                RenderCommand::AddGeometry {
                    transform,
                    parent_id,
                    mesh_handle,
                } => {
                    self.process_add_geometry_command(scene, transform, parent_id, mesh_handle);
                }
                RenderCommand::UpdateGeometryTransform {
                    segment_id,
                    transform,
                } => {
                    scene.transform_segment(segment_id, transform);
                }
                RenderCommand::RemoveSegment(nice_id) => {
                    // TODO: 可以考虑在移除时清理未使用的MeshData
                    scene.remove_segment(nice_id);
                }
                RenderCommand::Exit => {
                    // no need to process
                    log::debug!("<render_batch:process_commands> RenderCommand::Exit")
                }
                _ => (),
            }
        }
        scene.update_transforms();
    }

    fn process_add_geometry_command(
        &mut self,
        scene: &mut Scene,
        transform: Mat4,
        parent_id: Option<SegmentId>,
        mesh_handle: MeshHandle,
    ) {
        // 如果mesh_handle未注册，尝试注册一个空的MeshData
        if !scene.mesh_manager().contains(&mesh_handle) {
            // 创建一个空的MeshData作为占位符
            let empty_mesh_data = MeshData {
                vertices: Vec::new(),
                indices: Vec::new(),
            };
            scene
                .mesh_manager_mut()
                .register(mesh_handle, empty_mesh_data);
            log::warn!("警告: AddGeometry命令中的mesh_handle未注册, 已创建占位符");
        }

        // 分配新的段ID
        let instance_id = scene.db().allocate_id();

        // 3. 创建几何实例段（不是容器段）
        let geometry_instance = GeometryInstanceSegment::new(
            instance_id,
            mesh_handle,
            None, // 使用自动生成的标签
        );

        // 设置局部变换
        let mut geometry_instance_mut = geometry_instance;
        geometry_instance_mut.set_local_transform(transform);

        // 添加到场景（parent_id应该是geometry容器段的ID）
        let segment_id = scene.create_segment(geometry_instance_mut, parent_id);

        // 标记为脏，需要更新变换
        scene.mark_dirty(segment_id);
        scene.print_dirty_path();

        // 打印当前的段信息
        scene.db().print_path();
    }

    /// 检查是否应该刷新批处理
    pub(crate) fn should_flush(&self) -> bool {
        // 如果积累了足够的命令或者超过了最小刷新间隔，刷新批处理
        let command_threshold = 10; // 根据实际性能调整
        let time_threshold =
            self.last_flush_time.elapsed().as_millis() >= self.min_flush_interval_ms as u128;

        self.commands.len() >= command_threshold || time_threshold
    }

    /// 获取当前命令数量
    pub(crate) fn len(&self) -> usize {
        self.commands.len()
    }

    /// 是否为空
    pub(crate) fn is_empty(&self) -> bool {
        self.commands.is_empty()
    }

    pub(crate) fn update_dirty_segments(&mut self, scene: &mut Scene) {
        if self.dirty_segments.is_empty() {
            return;
        }

        let mut sorted_segments = Vec::new();
        for segment_id in &self.dirty_segments {
            sorted_segments.push(segment_id);
        }

        // TODO: 后续需要更复杂高效的拓扑排序 sorted_segments
        sorted_segments.sort();

        for segment_id in sorted_segments {
            let parent_world = if let Some(parent_id) = scene.db().get_parent(Some(segment_id)) {
                scene
                    .db()
                    .get_segment(&parent_id)
                    .map(|p| p.world_transform())
                    .unwrap_or(Mat4::IDENTITY)
            } else {
                Mat4::IDENTITY
            };

            Self::update_segment_recursive(scene, segment_id, parent_world);
        }
    }

    /// 递归更新段及其子段的变换
    pub(crate) fn update_segment_recursive(scene: &mut Scene, id: &SegmentId, parent_world: Mat4) {
        let world = {
            let segment = scene.db_mut().get_segment_mut(&id).unwrap();
            let local = segment.local_transform();
            let world = parent_world * local;
            segment.set_world_transform(world);
            segment.set_dirty(false);
            world
        };

        // 递归更新所有子段
        for child_id in scene.db().get_children(&id) {
            Self::update_segment_recursive(scene, &child_id, world);
        }
    }
}
